import { useState, useEffect, useRef } from 'react';
import { io } from 'socket.io-client';
import axios from 'axios';
import styles from './litaotian.module.css';
import userImage from '../../../assets/images/userImage.webp';
import yuyinGif from '../../../assets/images/yuyin.gif';
import emojiPng from '../../../assets/images/emoji.png';
import plusPng from '../../../assets/images/plus.png';

export default function Litaotian(props) {
    const username = props.username;
    // console.log(username);
    
    const [messageList, setMessageList] = useState([]);
    const [dispatcher, setDispatcher] = useState('');
    const [flag, setFlag] = useState('none');
    const [flag1, setFlag1] = useState('none');
    const [isSpeaking, setIsSpeaking] = useState(false);
    const chatMessagesContainer = useRef(null);

    const emojilist = [
        ['😀', '😁', '😂', '🤣', '😃', '😅', '😆'],
        ['😉', '😊', '😋', '😎', '😍', '😘', '😗'],
        ['😙', '😚', '🙂', '🤗', '🤔', '😐', '😑'],
        ['😶', '🙄', '😏', '😣', '😥', '😮', '🤐'],
        ['😯', '😪', '😫', '😴', '😌', '😛', '😜'],
        ['😝', '🤤', '😒', '😓', '😔', '😕', '🙃'],
        ['🤑', '😲', '🙁', '😖', '😟', '😤', '😢'],
        ['😭', '😧', '😨', '😩', '😬', '😰', '😳'],
        ['😱', '😵', '😡', '😠', '😷', '🤒', '🤕'],
    ];

    let recognition = null;
    let finalResult = '';
    let interimResult = '';

    // 定义一个函数，用于切换语音识别功能
    const toggleSpeechRecognition = () => {
        // 获取浏览器中的语音识别对象
        const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
        // 如果浏览器支持语音识别功能，并且recognition对象不存在
        if (!recognition && SpeechRecognition) {
            // 创建一个新的语音识别对象
            recognition = new SpeechRecognition();
            // 设置语音识别为连续识别
            recognition.continuous = true;
            // 设置语音识别为临时结果
            recognition.interimResults = true;
            // 设置语音识别的语言为中文
            recognition.lang = 'zh-CN';
            // 设置语音识别的结果回调函数
            recognition.onresult = (event) => {
                // 初始化临时结果
                interimResult = '';
                // 遍历语音识别的结果
                for (let i = event.resultIndex; i < event.results.length; i++) {
                    // 如果是最终结果，则添加到最终结果中
                    if (event.results[i].isFinal) {
                        finalResult += event.results[i][0].transcript;
                    // 否则，添加到临时结果中
                    } else {
                        interimResult += event.results[i][0].transcript;
                    }
                }
                // 设置状态中的dispatcher为最终结果和临时结果
                setDispatcher(finalResult + interimResult);
            };
            // 启动语音识别
            recognition.start();
            // 设置状态中的isSpeaking为true
            setIsSpeaking(true);
            // 打印日志，表示语音识别已启动
            console.log('语音识别已启动');
        } else if (!SpeechRecognition) {
            console.log('当前浏览器不支持语音识别功能');
        }
    };

    // 定义一个函数，用于停止语音识别
    const btnup = () => {
        // 如果recognition存在
        if (recognition) {
            // 停止语音识别
            recognition.stop();
            // 设置isSpeaking为false
            setIsSpeaking(false);
            // 将recognition置为null
            recognition = null;
            // 将finalResult置为空字符串
            finalResult = '';
            // 将interimResult置为空字符串
            interimResult = '';
            // 将dispatcher置为空字符串
            setDispatcher('');
        }
    };

    // 定义一个函数，用于打开弹窗
    const openPopup = () => {
        // 如果flag的值为'none'
        if (flag === 'none') {
            // 将flag的值设置为'block'
            setFlag('block');
            // 将flag1的值设置为'none'
            setFlag1('none');
        } else {
            // 否则，将flag的值设置为'none'
            setFlag('none');
            // 将flag1的值设置为'none'
            setFlag1('none');
        }
    };

    // 打开表情
    const openEmoji = () => {
        // 如果flag1为none
        if (flag1 === 'none') {
            // 设置flag1为block
            setFlag1('block');
            // 设置flag为none
            setFlag('none');
        } else {
            // 否则设置flag1为none
            setFlag1('none');
            // 设置flag为none
            setFlag('none');
        }
    };

    // 当按下回车键且没有按下shift键时，发送消息
    const sendOnEnter = (event) => {
        if (event.key === 'Enter' && !event.shiftKey) {
            send();
            event.preventDefault();
        }
    };

    const socket = io('ws://127.0.0.1:3001');

    useEffect(() => {
        socket.on('connection', () => {
            console.log('a user connected');
            socket.on('disconnect', () => {
                console.log('user disconnected');
            });
        });

        socket.on('message', (msg, user) => {
            let userobj = {
                username: user,
                message: msg,
                sendFailed: false,
            };
            if (navigator.onLine) {
                setMessageList((prevMessages) => [...prevMessages, userobj]);
            } else {
                userobj.sendFailed = true;
                setMessageList((prevMessages) => [...prevMessages, userobj]);
            }
        });

        socket.on('imageMessage', (data) => {
            console.log('Received image message: ', data);
            const imgBaseUrl = "http://localhost:3001/uploads";
            const imageName = data.path.split("\\").pop();
            const imageUrl = imgBaseUrl + '/' + imageName;
            console.log('最终路径', imageUrl);
            let sender = data.username ? data.username : username;
            let userobj = {
                username: sender,
                message: imageUrl,
                isImage: data.isUploaded || false,
                sendFailed: false,
            };
            setMessageList((prevMessages) => [...prevMessages, userobj]);
            console.log(messageList);
        });

        socket.on('audioMessage', (data) => {
            const audioBaseUrl = "http://localhost:3000/audioUploads";
            const audioName = data.path.split("\\").pop();
            const audioUrl = audioBaseUrl + '/' + audioName;
            console.log('Received audio URL:', audioUrl);
            let sender = data.username ? data.username : username;
            let userobj = {
                username: sender,
                message: audioUrl,
                isAudio: true,
                sendFailed: false
            };
            setMessageList((prevMessages) => [...prevMessages, userobj]);
            const audioElement = new Audio(audioUrl);
            audioElement.addEventListener('error', () => {
                console.error('Failed to play audio:', audioElement.error);
                alert('Failed to play audio');
            });
        });

        const onNetworkChange = () => {
            if (navigator.onLine) {
                // 网络连接恢复，可以进行一些操作，比如重新连接 socket
            } else {
                // 网络断开，进行相应处理
            }
        };

        window.addEventListener('online', onNetworkChange);
        window.addEventListener('offline', onNetworkChange);

        return () => {
            socket.off('connection');
            socket.off('message');
            socket.off('imageMessage');
            socket.off('audioMessage');
            window.removeEventListener('online', onNetworkChange);
            window.removeEventListener('offline', onNetworkChange);
        };
    }, [username]);

    // 发送消息
    const send = () => {
        // 创建新消息对象
        const newMessage = {
            username: username,
            message: dispatcher,
            sendFailed: false,
        };
        // 如果输入框中有内容且网络在线
        if (dispatcher && navigator.onLine) {
            // 发送消息
            socket.emit('message', dispatcher, username);
            // 清空输入框
            setDispatcher('');
            // 隐藏发送按钮
            setFlag('none');
            // 隐藏图片
            setFlag1('none');
            // 确保发送消息后关闭麦克风并隐藏图片
            btnup();
        // 如果网络不在线
        } else if (!navigator.onLine) {
            // 将消息添加到消息列表中，并将sendFailed属性设置为true
            setMessageList((prevMessages) => [...prevMessages, { ...newMessage, sendFailed: true }]);
            // 清空输入框
            setDispatcher('');
            // 确保发送消息后关闭麦克风并隐藏图片
            btnup();
        }
    };

    // 重新发送消息
    const resendMessage = (failedMessage) => {
        // 如果网络在线
        if (navigator.onLine) {
            // 发送消息
            socket.emit('message', failedMessage.message, username);
            // 过滤掉失败的消息
            const newMessageList = messageList.filter((msg) => msg!== failedMessage);
            // 更新消息列表
            setMessageList(newMessageList);
        } else {
            // 如果网络已断开，无法重新发送消息
            console.log('网络已断开，无法重新发送消息。');
        }
    };

    // 重新发送发送失败的消息
    const resendFailedMessages = () => {
        // 获取发送失败的消息列表
        const failedMessages = messageList.filter(item => item.sendFailed);
        // 遍历发送失败的消息列表
        failedMessages.forEach((failedMessage) => {
            // 发送消息
            socket.emit('message', failedMessage.message, username);
            // 更新消息列表，将发送失败的状态改为false
            const newMessageList = messageList.map((msg) => {
                if (msg === failedMessage) {
                    return { ...msg, sendFailed: false };
                }
                return msg;
            });
            // 更新消息列表
            setMessageList(newMessageList);
        });
    };

    // 选择图片
    const selectImage = () => {
        // 判断网络是否在线
        if (navigator.onLine) {
            // 创建一个input元素
            const input = document.createElement('input');
            // 设置input元素的类型为文件
            input.type = 'file';
            // 设置input元素接受图片类型
            input.accept = 'image/*';
            // 监听input元素的change事件
            input.onchange = async (event) => {
                // 获取用户选择的文件
                const file = event.target.files[0];
                // 如果文件存在
                if (file) {
                    // 创建一个FormData对象
                    const formData = new FormData();
                    // 将文件添加到FormData对象中
                    formData.append('image', file);
                    // 将用户名添加到FormData对象中
                    formData.append('username', username);
                    try {
                        // 发送POST请求，将FormData对象作为参数
                        await axios.post('http://127.0.0.1:3000/upload', formData, {
                            // 设置请求头
                            headers: {
                                'Content-Type': 'multipart/form-data',
                            },
                        });
                    } catch (error) {
                        // 如果上传图片失败，打印错误信息
                        console.error('上传图片失败：', error);
                    }
                }
            };
            // 触发input元素的click事件
            input.click();
        } else {
            // 如果网络已断开，打印提示信息
            console.log('网络已断开，无法上传图片。');
        }
    };

    // 滚动到底部
    const scrollToBottom = () => {
        // 如果聊天消息容器存在
        if (chatMessagesContainer.current) {
            // 将聊天消息容器的滚动条位置设置为消息容器的滚动高度加上10
            chatMessagesContainer.current.scrollTop = chatMessagesContainer.current.scrollHeight + 10;
        }
    };

    useEffect(() => {
        scrollToBottom();
    }, [messageList]);

    useEffect(() => {
        scrollToBottom();
    }, []);

    return (
        <div className={styles.sockAll}>
            <ul id="messages" ref={chatMessagesContainer} className={styles.messages}>
                {messageList.map((item, index) => (
                    <li
                        key={index}
                        className={username === item.username ? styles.mainer : styles.other}
                    >
                        <div className={styles.avatar}>
                            <img src={userImage} alt="" />
                        </div>
                        <div className={styles.words}>
                            {!item.isImage && !item.isAudio && <span>{item.message}</span>}
                            {item.isImage && <img src={item.message} alt="" />}
                            {item.isAudio && (
                                <audio
                                    src={item.message}
                                    controls
                                    style={{ width: '270px', height: '50px' }}
                                ></audio>
                            )}
                        </div>
                        {item.sendFailed && (
                            <div
                                className={styles.failedIconContainer}
                                onClick={() => resendMessage(item)}
                            >
                                <span className={styles.failedIcon}>&#10071;</span>
                            </div>
                        )}
                    </li>
                ))}
            </ul>
            <div
                id="saying"
                style={{ opacity: isSpeaking? 1 : 0 }}
                className={styles.saying}
            >
                <img src={yuyinGif} alt="" />
            </div>
            <div className={styles.navBottom}>
                <form
                    id="form"
                    onSubmit={(e) => e.preventDefault()}
                    className={styles.form}
                >
                    <input
                        id="input"
                        autoComplete="off" 
                        value={dispatcher}
                        onChange={(e) => setDispatcher(e.target.value)}
                        onKeyUp={sendOnEnter}
                        onKeyDown={(e) => { if (e.key === 'Enter') e.preventDefault(); }}
                        className={styles.input}
                    />
                    <button onClick={openEmoji} className={styles.emojiButton}>
                        <img src={emojiPng} alt="" />
                    </button>
                    {dispatcher.length > 0? (
                        <button onClick={send} className={styles.sendButton}>
                            发送
                        </button>
                    ) : (
                        <button onClick={openPopup} className={styles.plusButton}>
                            <img src={plusPng} alt="" />
                        </button>
                    )}
                </form><br />
                <div
                    id="popup"
                    style={{ display: flag }}
                    className={styles.popup}
                >
                    <div className={styles.grid}>
                        <div
                            className={styles.gridItem}
                            onClick={selectImage}
                        >
                            <svg t="1740357515653" className={styles.icon} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5077" width="200" height="200"><path d="M867.90864 574.538232V257.779543a50.844091 50.844091 0 0 0-50.844092-50.844091h-610.129096a50.844091 50.844091 0 0 0-50.844092 50.844091v499.797418l430.141013-257.779543a152.532274 152.532274 0 0 1 157.108243 0z m0 118.466733l-177.445879-106.264151a50.844091 50.844091 0 0 0-50.844092 0L254.220457 817.064548h562.844091a50.844091 50.844091 0 0 0 50.844092-50.844091z m-660.973188-587.757696h610.129096a152.532274 152.532274 0 0 1 152.532274 152.532274v508.440914a152.532274 152.532274 0 0 1-152.532274 152.532274h-610.129096a152.532274 152.532274 0 0 1-152.532274-152.532274v-508.440914a152.532274 152.532274 0 0 1 152.532274-152.532274z m127.110228 355.90864a76.266137 76.266137 0 1 1 76.266137-76.266137 76.266137 76.266137 0 0 1-76.266137 76.266137z" fill="#707070" p-id="5078"></path></svg>    
                            <span>图片</span>
                        </div>
                        <div
                            className={styles.gridItem}
                            onTouchStart={toggleSpeechRecognition}
                            onTouchEnd={btnup}
                        >   
                            <svg t="1740357802886" className={styles.icon} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6377" width="200" height="200"><path d="M829.44 901.421176h-81.618824l-26.202352-68.367058h-120.470589l-24.69647 68.367058h-80.112941l117.76-301.17647h94.569411z m-136.432941-143.962352l-32.527059-87.341177-30.72 87.04z" p-id="6378" fill="#707070"></path><path d="M301.176471 572.235294v361.411765a90.352941 90.352941 0 0 0 90.352941 90.352941h542.117647a90.352941 90.352941 0 0 0 90.352941-90.352941V572.235294a90.352941 90.352941 0 0 0-90.352941-90.352941H391.529412a90.352941 90.352941 0 0 0-90.352941 90.352941z m602.352941 361.411765H421.647059a30.117647 30.117647 0 0 1-30.117647-30.117647V602.352941a30.117647 30.117647 0 0 1 30.117647-30.117647h481.882353a30.117647 30.117647 0 0 1 30.117647 30.117647v301.176471a30.117647 30.117647 0 0 1-30.117647 30.117647z" p-id="6379" fill="#707070"></path><path d="M120.470588 572.235294a30.117647 30.117647 0 0 1-30.117647-30.117647V120.470588a30.117647 30.117647 0 0 1 30.117647-30.117647h783.058824a30.117647 30.117647 0 0 1 30.117647 30.117647v271.058824h90.352941V90.352941a90.352941 90.352941 0 0 0-90.352941-90.352941H90.352941a90.352941 90.352941 0 0 0-90.352941 90.352941v481.882353a90.352941 90.352941 0 0 0 90.352941 90.352941h120.470588v-90.352941z" p-id="6380" fill="#707070"></path><path d="M288.527059 204.8m45.17647 0l0 0q45.176471 0 45.176471 45.176471l0 90.352941q0 45.176471-45.176471 45.17647l0 0q-45.176471 0-45.17647-45.17647l0-90.352941q0-45.176471 45.17647-45.176471Z" p-id="6381" fill="#707070"></path><path d="M469.232941 174.682353m45.176471 0l0 0q45.176471 0 45.17647 45.176471l0 150.588235q0 45.176471-45.17647 45.17647l0 0q-45.176471 0-45.176471-45.17647l0-150.588235q0-45.176471 45.176471-45.176471Z" p-id="6382" fill="#707070"></path><path d="M649.938824 204.8m45.17647 0l0 0q45.176471 0 45.176471 45.176471l0 90.352941q0 45.176471-45.176471 45.17647l0 0q-45.176471 0-45.17647-45.17647l0-90.352941q0-45.176471 45.17647-45.176471Z" p-id="6383" fill="#707070"></path></svg>
                            <span>转文字</span>
                        </div>
                        <div className={styles.gridItem}>
                            <svg t="1740357859318" className={styles.icon} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7449" width="200" height="200"><path d="M511.424 2.624C230.272 2.624 2.304 230.528 2.304 511.744c0 281.152 227.904 509.12 509.12 509.12 281.152 0 509.12-227.904 509.12-509.12C1020.224 230.656 792.512 2.944 511.424 2.624z m0 939.84c-237.888 0-430.784-192.832-430.784-430.784 0-237.888 192.832-430.784 430.784-430.784 237.888 0 430.784 192.832 430.784 430.784-0.256 237.824-192.96 430.528-430.784 430.784z m0 0" p-id="7450" fill="#707070"></path><path d="M433.856 247.104a44.768 44.768 0 0 0-71.104 36.352v475.2a44.768 44.768 0 0 0 71.104 36.352l326.72-237.568a44.768 44.768 0 0 0 18.688-36.352c0-14.4-6.976-27.968-18.688-36.352L433.856 247.104z m0 0" p-id="7451" fill="#707070"></path></svg>
                            <span>开始录音</span>
                        </div>
                        <div className={styles.gridItem}>
                            <svg t="1740357903280" className={styles.icon} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8665" width="200" height="200"><path d="M512 0a512 512 0 1 1 0 1024A512 512 0 0 1 512 0z m0 85.357714a426.642286 426.642286 0 1 0 0 853.284572A426.642286 426.642286 0 0 0 512 85.357714z m85.357714 256a85.357714 85.357714 0 0 1 85.284572 85.284572v170.715428a85.357714 85.357714 0 0 1-85.284572 85.284572H426.642286a85.357714 85.357714 0 0 1-85.284572-85.284572V426.642286a85.357714 85.357714 0 0 1 85.284572-85.284572h170.715428z" fill="#707070" p-id="8666"></path></svg>
                            <span>结束录音</span>
                        </div>
                    </div>
                </div>
                <div
                    id="emoji"
                    style={{ display: flag1 }}
                    className={styles.emoji}
                >
                    {emojilist.map((row, rowIndex) => (
                        <div
                            key={rowIndex}
                            style={{ display: 'flex', justifyContent: 'space-between' }}
                            className={styles.emojiRow}
                        >
                            {row.map((emoji, emojiIndex) => (
                                <div
                                    key={emojiIndex}
                                    onClick={() => setDispatcher(dispatcher + emoji)}
                                    className={styles.emojiItem}
                                >
                                    {emoji}
                                </div>
                            ))}
                        </div>
                    ))}
                </div>
            </div>
        </div>
    );
}